<?php
/**
 * @file
 */
define('WG_HORIZONTAL', 0);
define('WG_VERTICAL', 1);

/**
 * Get random a word into dictionary
 * @param array $exclude
 * @return bool
 */
function wordgame_random_word($exclude = array()) {
  static $total, $words;
  if (!$total) {
    $total = wordgame_word_totals();
    if (!$total) {
      return ;
    }
  }
  if (!$words) {
    $words = db_select('wordgame_word' , 'w')->fields('w', array('wid'))->execute()->fetchCol();
  }
  $wid = $words[(rand(1, $total) + 1)];
  $conditions = array();
  if ($exclude) {
    $conditions = array(array('word', $exclude, "NOT IN"));
  }
  $word = wordgame_word_load($wid, $conditions);
  if ($word) {
    return $word;
  }
  else {
    return wordgame_random_word();
  }
}

/**
 * Random direction of word into board
 */
function wordgame_random_direction() {
  return rand(0, 1) ? WG_HORIZONTAL : WG_VERTICAL;
}

/**
 * Random position
 */
function wordgame_random_position($word, $wordgame) {
  // Get Column
  if ($wordgame->columns - $word->length < $word->length) {
    $column = $wordgame->columns - $word->length;
  }
  else {
    $column = rand($word->length, $wordgame->columns - $word->length);
  }
  // Get row
  if ($wordgame->rows - $word->length < $word->length) {
    $row = $wordgame->rows - $word->length;
  }
  else {
    $row = rand($word->length, $wordgame->rows - $word->length);
  }
  return array(
    'col' => $column,
    'row' => $row
  );
}

/**
 * Random position
 */
function wordgame_random_alphabet($word, $exclude = array()) {
  // Get position
  $pos = rand(0, strlen($word->word) - 1);
  // return alphabet
  if (in_array($word->word[$pos], $exclude)) {
    return wordgame_random_alphabet($word, $exclude = array());
  }
  else {
    return $word->word[$pos];
  }
}

/**
 * Put word into board
 */
function wordgame_mapping_word_board($word, &$wordgame) {
  $count = 0;
  $amount_guest = rand(1, ($wordgame->max_guest < $word->length ? $wordgame->max_guest : $word->length - 1));
  // Horizontal
  if ($word->direction == WG_HORIZONTAL) {
    $j = 0;
    for ($i = $word->position['row']; $i < ($word->position['row'] + $word->length); $i++) {
      // add alphabet to board
      if (!empty($wordgame->board[$i][$word->position['col']])) {
        $wordgame->board[$i][$word->position['col']]['word'][] = $word->word;
      }
      else {
        $wordgame->board[$i][$word->position['col']] = array(
          'letter' => $word->word[$j],
          'word' => array($word->word)
        );
      }
      // add position for each alphabet of word
      $word->string[] = array(
        'col' => $word->position['col'],
        'row' => $i,
        'letter' => $word->word[$j],
      );
      // Add guest alphabet
      if (rand(0, 1) && $count < $amount_guest ) {
        // Skip if guest ready
        if (empty($wordgame->guests[$i][$word->position['col']])) {
          $wordgame->guests[$i][$word->position['col']] = array('letter' => strtolower($word->word[$j]), 'word' => $word->word);
          $char = $word->word[$j];
          if (isset($wordgame->amounts[$char])) {
            $wordgame->amounts[$char]++;
          }
          else {
            $wordgame->amounts[$char] = 1;
          }
          $count++;
        }
      }
      $j++;
    }
  }
  // Vertical
  else {
    $j = 0;
    for ($i = $word->position['col']; $i < ($word->position['col'] + $word->length); $i++) {
      // add alphabet to board
      if (!empty($wordgame->board[$word->position['row']][$i])) {
        $wordgame->board[$word->position['row']][$i]['word'][] = $word->word;
      }
      else {
        $wordgame->board[$word->position['row']][$i] = array(
          'letter' => $word->word[$j],
          'word' => array($word->word)
        );
      }
      // add position for each alphabet of word
      $word->string[] = array(
        'col' => $i,
        'row' => $word->position['row'],
        'letter' => $word->word[$j]
      );
      // Add guest alphabet
      if (rand(0, 1) && $count < $amount_guest) {
        // Skip if guest ready
        if (empty($wordgame->guests[$i][$word->position['col']])) {
          $wordgame->guests[$word->position['row']][$i] = array('letter' => strtolower($word->word[$j]), 'word' => $word->word);
          $char = $word->word[$j];
          if (isset($wordgame->amounts[$char])) {
            $wordgame->amounts[$char]++;
          }
          else {
            $wordgame->amounts[$char] = 1;
          }
          $count++;
        }
      }
      $j++;
    }
  }
  $wordgame->words[$word->word] = $word;
}

/**
 * Get border for new word
 */
function wordgame_get_border($cell, $word, $wordgame) {
  $board = $wordgame->board;
  if ($word->direction == WG_HORIZONTAL) {
    // Left border
    $left = 0;
    for ($i = $cell['col'] - 1; $i >= 0; $i--) {
      if (!empty($board[$cell['row']][$i])) {
        break;
      }
      $left++;
    }
    // Right border
    $right = 0;
    for ($i = $cell['col'] + 1; $i <= $wordgame->columns; $i++) {
      if (!empty($board[$cell['row']][$i])) {
        break;
      }
      $right++;
    }
  }
  else {
    // Up border
    $top = 0;
    for ($i = $cell['row'] - 1; $i >= 0; $i--) {
      if (!empty($board[$i][$cell['col']])) {
        break;
      }
      $top++;
    }
    $bottom= 0;
    for ($i = $cell['row'] + 1; $i <= $wordgame->columns; $i++) {
      if (!empty($board[$i][$cell['col']])) {
        break;
      }
      $bottom++;
    }
  }
  return array(
    'first' => $word->direction == WG_HORIZONTAL ? $left : $top,
    'after' => $word->direction == WG_HORIZONTAL ? $right : $bottom,
  );
}

/**
 * load first word
 */
function wordgame_first_word(&$wordgame) {
  $word = wordgame_random_word();
  $word->status = 0;
  $word->direction = wordgame_random_direction();
  $word->position = wordgame_random_position($word, $wordgame);
  wordgame_mapping_word_board($word, $wordgame);
  $wordgame->words[$word->word] = $word;
  return $word;
}

/**
 * Load lastest wordgame
 */
function wordgame_latest_games() {
  global $user;
  $wordgame = wordgame_load_by_uid($user->uid);
  if (!$wordgame) {
    // Prepare object wordgame
    $wordgame = new StdClass();
    // Save game
    wordgame_save($wordgame);

    // Update user level
    $level = wordgame_user_level($user->uid);
    $level->played = $level->played + 1;
    wordgame_user_level_save($level);
  }
  return $wordgame;
}

/**
 * Choose Guest Word
 */
function wordgame_summon_word($word, &$wordboard) {
  $total_summon = rand(1, $wordboard->max_summon ? $wordboard->max_summon : $word->length - 1);
  for ($i = 0; $i < $total_summon; $i++) {
    $char = $wordboard->words[$word->word]->string[rand(0, $word->length - 1)];
    $border = wordgame_get_border($char, $word, $wordboard);
    // Summon new word
    $summon_words = wordgame_word_load_multiple_extra($char['letter'], $border, array_keys($wordboard->words));
    if (empty($summon_words)) {
      continue ;
    }
    $word_index = rand(0, count($summon_words));
    if ($word_index) {
      $summon_word = isset($summon_words[$word_index]) ? $summon_words[$word_index] : FALSE;
      if (!$summon_word) {
        continue ;
      }
    }
    else {
      continue;
    }
    $summon_word->direction = $word->direction ? WG_HORIZONTAL : WG_VERTICAL;
    $position = strpos($summon_word->word, $char['letter']);
    if ($summon_word->direction == WG_HORIZONTAL) {
      $summon_word->position['col'] = $char['col'];
      $summon_word->position['row'] = ($char['row'] - ($position));
    }
    else {
      $summon_word->position['row'] = $char['row'];
      $summon_word->position['col'] = ($char['col'] - ($position));
    }
    wordgame_mapping_word_board($summon_word, $wordboard);
    wordgame_summon_word($summon_word, $wordboard);
  }
}

/**
 * Finish games
 */
function wordgame_is_finished($wordgame) {
  $guests = $wordgame->guests;
  if ($guests) {
    return FALSE;
  }
  return TRUE;
}